home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / windows4 / pcproj.zip / PROJECT.CLS < prev    next >
Text File  |  1989-10-26  |  7KB  |  291 lines

  1. /* A Project is a network of Task and Milestone nodes to
  2.    manage CPM or PERT networks.  A project knows how to
  3.    calculate its critical path, keep track of costs etc.
  4.  
  5.    Since Project descends from Network, it inherits all of
  6.    Network's instance variables, e.g. start, end, name, desc.
  7. */!!
  8.  
  9. inherit(Network, #Project, #(cost      /* sum of all costs */
  10. resources /* used by tasks */
  11. autoCalc  /* boolean is recalc on? */
  12.  
  13. ), 2, nil)!!
  14.  
  15. now(ProjectClass)!!
  16.  
  17. now(Project)!!
  18.  
  19. /* Return only the tasks in the project. */
  20. Def  tasks(self)
  21.   ^extract(nodes(self),
  22.    {using(node) 
  23.     class(node) <> Milestone;
  24.    });
  25. }!!
  26.  
  27. /* Returns a collection of lines summarizing useful information. */
  28. Def  getInfoLines(self | tc)
  29. {
  30.   tc := new(OrderedCollection, 6);
  31.   add(tc, loadString(PW_PROJECT) + ": " + field(name, 8)+ "   " + desc);
  32.   add(tc, "");
  33.   add(tc, loadString(PW_PROJT1));
  34.   add(tc, "--------------------------------------------");
  35.   add(tc, loadString(PW_START)
  36.    + field(asString(getEarlyStart(self)), 8) + " "
  37.    + field(asString(getLateStart(self)), 8) + " "
  38.    + field(asString(getCost(self)), 6) + " "
  39.    + field(asString(getTime(self)), 6) + " " 
  40.    + field(asString(getSlack(self)), 4));
  41.   add(tc, loadString(PW_FINISH)
  42.    + field(asString(getEarlyFinish(self)), 8) + " "
  43.    + field(asString(getLateFinish(self)), 8));
  44.   ^tc;
  45.  }!!
  46.  
  47. /* Return the resource if the name exists in the
  48.    resources collection, otherwise return false and
  49.    display an error message. */
  50. Def  checkResExists(self, resName | res)
  51. {
  52.   if not(res := resExists(self, resName))
  53.     beep();
  54.     errorBox(loadString(PW_RESINVAL),
  55.              loadString(PW_RESOURCE) + " " + resName +
  56.              loadString(PW_NOTEXIST));
  57.   endif;
  58.   ^res;
  59. }!!
  60.  
  61. /* Return the resources collection. */
  62. Def  resources(self)
  63.   ^resources;
  64. }!!
  65.  
  66. /* Return the resource of the name resName if
  67.    it exists, otherwise return false. Use
  68.    checkResExists for error checking. */
  69. Def  resExists(self, resName | res)
  70. {
  71.   ^resName in resources;
  72. }!!
  73.  
  74. /* Parse a string of resNames and return a set of
  75.    resources.  If the resource doesn't exist, a new
  76.    one is created. */
  77. Def  parseResNames(self, resNames | names, res, aRes)
  78. {
  79.   names := words(resNames);
  80.   res := new(OrderedCollection, 6);
  81.   do(names,
  82.     {using(name) 
  83.      if not(aRes := resExists(self, name))  /* create it */
  84.        aRes := new(Resource);
  85.        setName(aRes, name);
  86.        if editInfo(aRes) == IDOK
  87.          add(resources, getName(aRes), aRes);
  88.          add(res, aRes);
  89.        endif;
  90.      else
  91.        add(res, aRes);
  92.      endif;
  93.   });
  94.   ^res;
  95. }!!
  96.  
  97. /* Return a sorted collection of activities in the project. 
  98.    Sort by earlyStart, time, name for unique order.  
  99.    This uses early binding and dot notation for speed. */
  100. Def  sortedActivities(self| sorted)
  101. {  
  102.   sorted := new(SortedCollection, 10);
  103.     
  104.   setCompareBlock(sorted, {using(a,b)
  105.                   if a.earlyStart = b.earlyStart
  106.                      if getTime(a) = getTime(b)
  107.                        a.name < b.name
  108.                      else
  109.                        getTime(a) < getTime(b)
  110.                      endif
  111.                   else
  112.                       a.earlyStart < b.earlyStart
  113.                  endif});
  114.  
  115.   do(nodeNames,
  116.      {using(aNode) 
  117.       add(sorted:SortedCollection, aNode);
  118.    });
  119.   ^sorted;
  120. }!!
  121.  
  122. /* Return the type of nodes that start and end should be.*/
  123. Def  nodeClass(self)
  124. {
  125.   ^Milestone;
  126. }!!
  127.  
  128. /* Return the current cost which is always up to date. */
  129. Def  getCost(self)
  130. {
  131.   ^cost;
  132. }!!
  133.  
  134. /* Get the user set late finish date. */
  135. Def  getUserLateFinish(self)
  136.   ^getUserLateFinish(end);
  137. }!!
  138.  
  139. /* Get the user set early start date. */
  140. Def  getUserEarlyStart(self)
  141.   ^getUserEarlyStart(start);
  142. } !!
  143.  
  144. /* Return a string to be used as a window caption. */
  145. Def  makeCaption(self)
  146. {
  147.   ^loadString(PW_PROJECT) + ": " + name;
  148. }!!
  149.  
  150. /* Set the values of a project. 
  151.    Values is an array of name, desc,
  152.    userEarlyStart, userLateFinish. 
  153.    This message is sent after editing. */
  154. Def  setValues(self, values)
  155. {
  156.   name := values[0];
  157.   desc := values[1];
  158.   if getEarlyStart(self) <> values[2]
  159.     setEarlyStart(self, values[2]);
  160.   endif;
  161.   if getLateFinish(self) <> values[3]
  162.     setLateFinish(self, values[3]);
  163.   endif;
  164. }!!
  165.  
  166. /* Display and edit the project information. 
  167.    The dialog should define methods run() and setEditItem().
  168. */
  169. Def  editInfo(self | dlg, retValue)
  170. {
  171.   showWaitCurs();
  172.   dlg := new(ProjDialog); 
  173.   setEditItem(dlg, self);
  174.   retValue := run(dlg, ThePort);
  175.   showOldCurs();
  176.   ^retValue;
  177. }!!
  178.  
  179. /* Project slack is defined as the slack at the end node.
  180.    This could be introduced if the user sets a lateFinish. */
  181. Def  getSlack(self)
  182. {
  183.   ^getSlack(end);
  184. }!!
  185.  
  186. /* Return the current cost which is always up to date. */
  187. Def  calcCost(self)
  188. {
  189.   ^cost;
  190. }!!
  191.  
  192. /* Update the cost based on a change to a Task. */
  193. Def  updateCost(self, change)
  194.   cost := cost + change;
  195. }!!
  196.  
  197. /* Do the backwards pass only starting from the end node.
  198.    The end node is always critical.
  199. */
  200. Def  recalc2(self)
  201. {  
  202.    recalc2(end);
  203.    end.critical := true;
  204. }!!
  205.  
  206. /* Turn automatic calculation on or off.
  207.    Force recalculation if turned on. */
  208. Def  setAutoCalc(self, mode)
  209. {
  210.   if (autoCalc := mode)   /* true or false */
  211.     recalc(self);    
  212.   endif;
  213. }!!
  214.  
  215. /* Recalculate the entire network. First invalidate all nodes
  216.    so that a full recalc will be forced.  Then do both the
  217.    forward and backwards recalc passes. The forward pass must
  218.    be entirely completed before doing the backwards pass. */
  219. Def  recalc(self)
  220. {
  221.    invalidate(start, new(Set,10)); /* clear all nodes */
  222.    recalc1(start, true);           /* force entire recalc */
  223.    recalc2(self);                  /* backwards pass */
  224. }!!
  225.  
  226. /* Get the project lateStart date. */
  227. Def  getLateStart(self)
  228.   ^getLateStart(start);
  229. }!!
  230.  
  231. /* Get the project earlyStart date. */
  232. Def  getEarlyStart(self)
  233.   ^getEarlyStart(start);
  234. } !! 
  235.  
  236. /* Get the project early finish date. */
  237. Def  getEarlyFinish(self)
  238.   ^getEarlyFinish(end);
  239. }!!
  240.  
  241. /* Get the project late finish date. */
  242. Def  getLateFinish(self)
  243.   ^getLateFinish(end);
  244. }!!
  245.  
  246. /* Return the status of autoCalc mode. */
  247. Def  autoCalc(self)
  248. {
  249.   ^autoCalc;
  250. }!!
  251.  
  252. /* The user can enter an early start date. */
  253. Def  setEarlyStart(self, aDate)
  254.   setEarlyStart(start,aDate);
  255. }!!
  256.  
  257. /* The user can enter a late finish date. */
  258. Def  setLateFinish(self, aDate)
  259.   setLateFinish(end,aDate);
  260. }!!
  261.  
  262. /* Calculate the project time. If negative (e.g. project
  263.    isn't fully hooked up yet) return 0. */
  264. Def  getTime(self)
  265. { ^max(0, getEarlyFinish(self) - getEarlyStart(self));
  266. }!!
  267.  
  268. /* Initialize a new Project. Uses ancestor init.
  269.    The nodeClass method determines the node type
  270.    for start and end. */
  271. Def  init(self)
  272.   init(self:Network);         /* use ancestor init */
  273.   cost := 0;
  274.   resources := new(Dictionary, 10);
  275.   setEarlyStart(start,        /* set default project start */
  276.     date(1,1,1988)); 
  277. }!!
  278.  
  279.